package com.laomo.lib_bt.ota;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;

import com.jieli.jl_bt_ota.constant.StateCode;
import com.jieli.jl_bt_ota.interfaces.IUpgradeCallback;
import com.jieli.jl_bt_ota.util.BluetoothUtil;
import com.laomo.lib_bt.BleManager;
import com.laomo.lib_bt.callback.CharacteristicCallbackInterface;
import com.laomo.lib_bt.callback.ConnectCallbackInterface;
import com.laomo.lib_bt.callback.OtaAvailableCallbackInterface;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 类说明：
 *
 * @author laomo
 * @date 2025/4/22 16:41
 */
public class OTAUtil implements ConnectCallbackInterface, CharacteristicCallbackInterface, IBleOp, OtaAvailableCallbackInterface {
    private OTAManager mOTAManager;
    private SendBleDataThread mSendBleDataThread;
    //ota就绪回调监听
    private List<OtaAvailableCallbackInterface> mOtaAvailableCallbackList = new ArrayList<>();

    private static OTAUtil sOTAUtil;

    private int mMtu = 100;

    private OTAUtil(Context context) {
        mOTAManager = new OTAManager(context);
        BleManager.getInstance(context).addConnectCallbackListener(this);
        BleManager.getInstance(context).addCharacteristicCallbackListener(this);
    }

    public static OTAUtil getInstance(Context context) {
        if (sOTAUtil == null) {
            synchronized (OTAUtil.class) {
                if (sOTAUtil == null) {
                    sOTAUtil = new OTAUtil(context);
                }
            }
        }
        return sOTAUtil;
    }


    public boolean isOTA(){
        return mOTAManager.isOTA();
    }


    public void addOtaAvailableCallbackListener(OtaAvailableCallbackInterface otaAvailableCallbackInterface) {
        if (otaAvailableCallbackInterface != null && !mOtaAvailableCallbackList.contains(otaAvailableCallbackInterface)) {
            mOtaAvailableCallbackList.add(otaAvailableCallbackInterface);
        }
    }

    public void removeOtaAvailableCallbackListener(OtaAvailableCallbackInterface otaAvailableCallbackInterface) {
        mOtaAvailableCallbackList.remove(otaAvailableCallbackInterface);
    }

    @Override
    public void onConnecting(String address, BluetoothDevice device) {
        mOTAManager.onBtDeviceConnection(device, StateCode.CONNECTION_CONNECTING);
    }

    @Override
    public void onMtuChanged(String address, BluetoothGatt gatt, int mtu, int status) {
        mMtu = mtu;
        mOTAManager.onMtuChanged(gatt, mtu, status);
    }

    @Override
    public void onConnectSuccess(String address, BluetoothGatt gatt) {
        startSendDataThread();
        mOTAManager.onBtDeviceConnection(gatt.getDevice(), StateCode.CONNECTION_OK);
    }

    @Override
    public void onConnectFailed(String address, BluetoothDevice device) {
        mOTAManager.onBtDeviceConnection(device, StateCode.CONNECTION_DISCONNECT);
    }

    @Override
    public void onDisConnect(String address, BluetoothGatt gatt) {
        mOTAManager.onBtDeviceConnection(gatt.getDevice(), StateCode.CONNECTION_DISCONNECT);
    }

    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        if (null == gatt) return;
        BluetoothDevice device = gatt.getDevice();
        if (null == device) return;
        if (null == characteristic) return;
        UUID serviceUUID = null;
        UUID characteristicUUID = characteristic.getUuid();
        BluetoothGattService gattService = characteristic.getService();
        if (gattService != null) {
            serviceUUID = gattService.getUuid();
        }
        wakeupSendThread(gatt, serviceUUID, characteristicUUID, status, characteristic.getValue());
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] value) {
        mOTAManager.onReceiveDeviceData(gatt.getDevice(), value);
    }

    @Override
    public int getBleMtu() {
        return mMtu-20;
    }

    public BluetoothGatt getLatestConnectedBtGatt() {
        return BleManager.getInstance(null).getLatestConnectedBtGatt();
    }

    @Override
    public boolean writeDataByBle(BluetoothGatt gatt, UUID serviceUUID, UUID characteristicUUID, byte[] data) {
        return BleManager.getInstance(null).write(gatt, serviceUUID, characteristicUUID, data);
    }

    private void startSendDataThread() {
        if (mSendBleDataThread == null) {
            mSendBleDataThread = new SendBleDataThread(this, new OnThreadStateListener() {
                @Override
                public void onStart(long id, String name) {

                }

                @Override
                public void onEnd(long id, String name) {
                    mSendBleDataThread = null;
                }
            });
            mSendBleDataThread.start();
        }
    }

    private void wakeupSendThread(BluetoothGatt gatt, UUID serviceUUID, UUID characteristicUUID, int status, byte[] data) {
        if (mSendBleDataThread != null) {
            SendBleDataThread.BleSendTask task = new SendBleDataThread.BleSendTask(gatt, serviceUUID, characteristicUUID, data, null);
            task.setStatus(status);
            mSendBleDataThread.wakeupSendThread(task);
        }
    }

    private void addSendTask(BluetoothDevice device, UUID serviceUUID, UUID characteristicUUID, byte[] data, OnWriteDataCallback callback) {
        boolean ret = false;
        BluetoothGatt latestConnectedBtGatt = getLatestConnectedBtGatt();
        if (mSendBleDataThread != null && latestConnectedBtGatt != null && BluetoothUtil.deviceEquals(device, latestConnectedBtGatt.getDevice())) {
            ret = mSendBleDataThread.addSendTask(latestConnectedBtGatt, serviceUUID, characteristicUUID, data, callback);
        }
        if (!ret) {
            callback.onBleResult(device, serviceUUID, characteristicUUID, false, data);
        }
    }

    public void writeDataByBleAsync(BluetoothDevice device, UUID serviceUUID, UUID characteristicUUID, byte[] data, OnWriteDataCallback callback) {
        addSendTask(device, serviceUUID, characteristicUUID, data, callback);
    }

    @Override
    public void onOtaAvailable(BluetoothDevice device, boolean isMandatoryUpgrade) {
        for (OtaAvailableCallbackInterface otaAvailableCallbackInterface : mOtaAvailableCallbackList) {
            otaAvailableCallbackInterface.onOtaAvailable(device, isMandatoryUpgrade);
        }
    }

    public void startOta(String address, byte[] data, IUpgradeCallback callback) {
        if (mOTAManager != null && !mOTAManager.isOTA()) {
            mOTAManager.getBluetoothOption().setFirmwareFileData(data);
            mOTAManager.startOTA(callback);
        }
    }
}
